#include "WindowSystem.h"
#include "resource.h"
#include "SoloClientConfiguration.h"
#include "EngineMessages.h"
#include "WindowSystemMessages.h"
#include "EngineLog.h"
#include "ItemDator.h"

WindowSystem* WindowSystem::currentSystem = NULL;

WindowSystem::WindowSystem(EnginePointer<SettingsManager>& settings, EnginePointer<IMessageQueue>& messages)
:IEngineSystem(settings, messages)
{
	hWnd = NULL;
	state = NEW;
	currentSystem = this;
}

WindowSystem::~WindowSystem()
{
}

HRESULT WindowSystem::Initialize(EnginePointer<SystemCollection>& systems)
{
	UNREFERENCED_PARAMETER(systems);

	HRESULT result;

	result = this->InitializeWindow();
	if (FAILED(result)) return result;

	ShowWindow(hWnd, SW_SHOW);
	state = RUNNING;

	return S_OK;
}

void WindowSystem::Update(LONGLONG timeElapsed)
{
	UNREFERENCED_PARAMETER(timeElapsed);

	MSG msg = {0};
	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	if (state == CLOSING)
	{
		Message m;
		m.messageId = ENGINE_QUIT_MESSAGE;
		m.uiParam = 0;
		messages->Enqueue(m);
		state = CLOSED;
	}
}

LRESULT CALLBACK WindowSystem::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;

	switch (message)
	{
		case WM_SIZE:
			if (currentSystem->state == RUNNING) currentSystem->SendResizedMessage();
			break;
		case WM_PAINT:
			BeginPaint(hWnd, &ps);
			EndPaint(hWnd, &ps);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			currentSystem->Destroy();
			break;
		case WM_CLOSE:
			currentSystem->Close();
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}

HRESULT WindowSystem::InitializeWindow()
{
	HINSTANCE hInst = GetModuleHandle(NULL);

	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInst;
	wcex.hIcon = LoadIcon(hInst, (LPCTSTR)IDI_ICON1);
	wcex.hIconSm = LoadIcon(hInst, (LPCTSTR)IDI_ICON1);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = L"D3D10Engine";

	if (!RegisterClassEx(&wcex))
		return E_FAIL;

	RECT rc;
	rc.left = 100;
	rc.top = 100;
	rc.right = 740;
	rc.bottom = 580;
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
	hWnd = CreateWindow(L"D3D10Engine", L"D3D10Engine", WS_OVERLAPPEDWINDOW, rc.left, rc.top, rc.right-rc.left, rc.bottom - rc.top, NULL, NULL, hInst, NULL);

	if (!hWnd)
		return E_FAIL;

	return S_OK;
}

GUID WindowSystem::getSystemIdentifier()
{
	return WINDOW_SYSTEM_GUID;
}

HWND WindowSystem::getHWnd()
{
	return hWnd;
}

void WindowSystem::SendResizedMessage()
{
	Message m;
	m.messageId = WINDOW_RESIZED_MESSAGE;
	m.uiParam = 0;
	messages->Enqueue(m);
}

void WindowSystem::Close()
{
	state = CLOSING;
}

void WindowSystem::Destroy()
{
	state = DESTROYED;
}

void WindowSystem::Clean()
{
	state = DESTROYING;
	DestroyWindow(hWnd);
	hWnd = 0;
}

BOOL WindowSystem::IsClean()
{
	return state == NEW || state == DESTROYED;
}
